# -*- coding: utf-8 -*-
"""
此文件中定义了主窗口要调用的相关子窗口，包括：
策略回测
策略运行监控
策略指标编辑
数据管理器
下单界面
常用统计方法界面
登录界面
account

"""
import importlib
import pickle
from os import path
import pyqtgraph as pg
from qtpy import QtWidgets,QtCore,QtGui,QtCharts

from PyQt6.QtCore import pyqtSlot, QDateTime, pyqtSignal
# from qtpy.QtCore import pyqtSlot,
from PyQt6.QtWidgets import QMainWindow, QFileDialog, QMessageBox
from PyQt6.uic import loadUi, loadUiType
import pandas as pd

import instrument.manager as IM
import engine.strategy_engine as StraEE
# import .newclicked
import w_dm
import  wQuote
import .w_bank_investor
from config.configpath import pyqt_ui_path
from config.system_conf import get_quote_server_dict, main_future_id, market_future_id
from const_struct.ctp_data_type import *
from dbhelper.box_db import DbHelper
from dbhelper.ctp_db_helper import load_future_market_product, load_market_future
from strategy.strategy_setting import get_strategy_setting
from .frm_order import Ui_Frame
from .three_list_widget import Ui_ThreeListWidget
from .bq_widget import *
from .ui_tools.kline_helper import *
from .ui_tools.pandas_model import PandasModel
from .wBacktest import Ui_StrategyBacktest
from .w_dm import Ui_DataManager
from .wFormulaEditor import Ui_FormulaEditor
from .wStrategyRunningMonitor import Ui_StrategyRunningMonitor
from .wTA import Ui_FormTA
from .dw_account import Ui_DockWidgetAccount

importlib.reload(wBacktest)
importlib.reload(frameOrder)
importlib.reload(w_bank_investor)
importlib.reload(w_dm)

OrderForm, OrderBase = loadUiType(path.join(pyqt_ui_path, 'frm_order.ui'))
StrategyBacktestForm, StrategyBacktestBase = loadUiType(path.join(pyqt_ui_path, 'wBacktest.ui'))
StrategyRunningMonitorForm, StrategyRunningMonitorBase = loadUiType(
    path.join(pyqt_ui_path, 'wStrategyRunningMonitor.ui'))
DataManagerForm, DataManagerBase = loadUiType(path.join(pyqt_ui_path, 'wDataManager.ui'))
FormulaEditorForm, FormulaEditorBase = loadUiType(path.join(pyqt_ui_path, 'wFormulaEditor.ui'))
TAForm, TABase = loadUiType(path.join(pyqt_ui_path, 'wTA.ui'))
AccountForm, AccountBase = loadUiType(path.join(pyqt_ui_path, 'w_account2.ui'))
QuoteForm, QuoteBase = loadUiType(path.join(pyqt_ui_path, 'wQuote.ui'))
# 指标大类
INDICATOR_TYPE_TI = '技术指标'
INDICATOR_TYPE_TRADE_STRATEGY = '交易策略'

from config.system_conf import ss_future


class QuoteMonitor(QuoteBase, wQuote.QuoteWidget):
    """"""

    def __init__(self, quote_event_engine=None):
        super(QuoteMonitor, self).__init__()
        self.setupUi(self)
        self.setWindowTitle('行情列表')
        self.quote_event_engine = quote_event_engine
        self.ssi = ss_future
        self.shfe = []
        self.czce = []
        self.dce = []
        self.cffex = []
        self.market_instrument_dict = market_future_id
        # print(self.market_instrument_dict)
        # 期货、市场字典
        self.shfe = self.market_instrument_dict.get(EXCHANGE_SHFE, [])
        self.cffex = self.market_instrument_dict.get(EXCHANGE_CFFEX, [])
        self.czce = self.market_instrument_dict.get(EXCHANGE_CZCE, [])
        self.dce = self.market_instrument_dict.get(EXCHANGE_DCE, [])
        self._create_quote_table()
        self.current_instrument_id = ''
        self.last_price = 0.0

    def _create_quote_table(self):
        """"""
        # 自选标的行情
        self.ssiTable = MarketTickMonitor(self.quote_event_engine, parent=self.tabSelfFuture, symbolSet=self.ssi,
                                          mainWindow=self, name='self_selected')
        self.ssiLayout.addWidget(self.ssiTable)
        self.shfeTable = MarketTickMonitor(self.quote_event_engine, parent=self.tabSHFE, symbolSet=self.shfe,
                                           mainWindow=self)
        self.SHFELayout.addWidget(self.shfeTable)
        self.czceTable = MarketTickMonitor(self.quote_event_engine, parent=self.tabCZCE, symbolSet=self.czce,
                                           mainWindow=self)
        self.CZCELayout.addWidget(self.czceTable)
        self.dceTable = MarketTickMonitor(self.quote_event_engine, parent=self.tabDCE, symbolSet=self.dce,
                                          mainWindow=self)
        self.DCELayout.addWidget(self.dceTable)
        self.cffexTable = MarketTickMonitor(self.quote_event_engine, parent=self.tabCFFEX, symbolSet=self.cffex,
                                            mainWindow=self)
        self.CFFEXLayout.addWidget(self.cffexTable)

        self.twChinaFuture.setTabText(self.twChinaFuture.indexOf(self.tabMainFuture), '主力合约')
        tw = self.twChinaA
        tw.setTabText(tw.indexOf(self.tabCASIndex), 'A股指数')
        tw.setTabText(tw.indexOf(self.tabCSE), '创业板')
        tw.setTabText(tw.indexOf(self.tabSZSE), '深主板')
        tw.setTabText(tw.indexOf(self.tabSHSE), '上主板')
        tw.setTabText(tw.indexOf(self.tabMSSE), '中小板')
        tw.setTabText(tw.indexOf(self.tabSCSE), '科创板')
        tw.setTabText(tw.indexOf(self.tabSelf), '自选股')

        tab = self.tabMainFuture
        MainFutureLayout = QtWidgets.QHBoxLayout(tab)
        MainFutureLayout.setObjectName("MainFutureLayout")
        mainFutureTable = MarketTickMonitor(self.quote_event_engine, parent=tab, symbolSet=main_future_id,
                                            mainWindow=self)
        MainFutureLayout.addWidget(mainFutureTable)

        self._register_widget_events()

        # print(self.shfe)

    def _register_widget_events(self):
        """注册控件事件"""
        self.ssiTable.cellClicked.connect(self.quote_table_widget_cell_clicked)
        self.shfeTable.cellClicked.connect(self.quote_table_widget_cell_clicked)
        self.dceTable.cellClicked.connect(self.quote_table_widget_cell_clicked)
        self.czceTable.cellClicked.connect(self.quote_table_widget_cell_clicked)
        self.cffexTable.cellClicked.connect(self.quote_table_widget_cell_clicked)

    def quote_table_widget_cell_clicked(self, x, y):
        """行情列表单元格单击事件"""
        # print(self.sender().parent().objectName(), self.ssiTable.item(x, 0).text())
        self.current_instrument_id = self.sender().item(x, 0).text()
        self.last_price = float(self.sender().item(x, 1).text())


class TLW(Ui_ThreeListWidget):
    def __init__(self, data=None, lw1='lw1', lw2='lw2', lw3='lw3'):
        """

        :param data:
        :param lw1:
        :param lw2:
        :param lw3:
        """
        super(TLW, self).__init__()
        self.data = data
        self.lw1.setObjectName(*lw1)
        self.lw2.setObjectName(*lw2)
        self.lw3.setObjectName(*lw3)


class BankInvestor(QMainWindow, .w_bank_investor.Ui_FormBankInvestor):
    """转账窗口"""

    def __init__(self, account_server=None):
        super(BankInvestor, self).__init__()
        self.setupUi(self)
        self.account_server = account_server

    def _init_widget(self):
        """"""

    def on_pbBank2Investor_clicked(self):
        """银行转投资"""
        if self.account_server is None:
            return
        evt = Event(event_type=EVENT_REQ_BANK_FUTURE)
        # self.account_server.

    def register_widget_event(self):
        """注册事件"""
        self.pbBank2Investor.clicked.connect(self.on_pbBank2Investor_clicked)
        self.pbInvestor2Bank.clicked.connect(self.on_pbBank2Investor_clicked)


class OrderPad(OrderBase, Ui_FrameOrder):
    """下单面板"""

    # ToDo 当持仓或持仓明细发来平仓信号时要处理
    # todo 测试对大期所、郑期所平昨指令的反应
    #  委托发送信号, 由交易管理接收（或者订阅)
    sendOrderSignal = pyqtSignal(object)

    def __init__(self, parent=None, quote_event=None, trade_event=None):
        super(OrderPad, self).__init__()
        self.setupUi(self)
        # 市场及标的信息

        if parent and 'market_instrument_dict' in parent.__dict__:
            self.market_instrument_dict = parent.market_instrument_dict
        else:
            self.market_instrument_dict = load_market_future()
        self.instrument_info = {}
        for k, v in self.market_instrument_dict.items():
            if not self.instrument_info:
                self.instrument_info = v.copy()
            else:
                self.instrument_info.update(v)
        # print(self.instrument_info)
        self.quote_event = quote_event
        self.trade_event = trade_event
        self.parent = parent
        self.symbol = ''

        if self.parent:
            self.parent.instrument_changed.connect(self.on_instrument_changed)

        if self.quote_event:
            self.quote_event.register(EVENT_TICK, self.update_data)

        # 设置下单窗口始终处于前端
        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)

        self.volume_multiple = 10
        self.price_tick = 1.0
        self.exchange_id = ''

        self._register_widget_event()

    def _register_widget_event(self):
        self.pushButtonOrder.clicked.connect(self.order_clicked)
        self.pushButtonPriceType.clicked.connect(self.pbPriceType_clicked)
        self.spinBoxPrice.valueChanged.connect(self.spinBoxPrice_valueChanged)
        self.toolButtonBuy.clicked.connect(self.buy_clicked)
        self.toolButtonSell.clicked.connect(self.sell_clicked)
        self.toolButtonShort.clicked.connect(self.short_clicked)
        self.toolButtonCover.clicked.connect(self.cover_clicked)

        self.comboBoxSymbol.focusOutEvent = self.comboBoxSymbol_focusOutEvent

        self.comboBoxSymbol.setEditable(True)
        self.comboBoxSymbol.addItems([k for k in self.instrument_info.keys()])

    def comboBoxSymbol_focusOutEvent(self, e):
        iid = self.comboBoxSymbol.currentText()

        if iid in self.instrument_info.keys():
            ii = self.instrument_info.get(iid, {})
            # print(iid)
            if ii:
                self.symbol = iid
                self.price_tick = ii.get('priceTick', ii.get('PriceTick', self.price_tick))
                self.exchange_id = ii.get('ExchangeID', self.exchange_id)
                self.spinBoxPrice.setSingleStep(self.price_tick)
                # print(self.price_tick)
                if self.parent:
                    self.spinBoxPrice.setValue(self.parent.last_price)

    @pyqtSlot(str)
    def on_instrument_changed(self, iid):
        # self.lineEditSymbol.setText(iid)
        self.symbol = iid
        self.comboBoxSymbol.setEditable(True)
        self.comboBoxSymbol.setEditText(iid)

        ii = self.instrument_info.get(iid, {})
        if ii:
            self.price_tick = ii.get('priceTick', ii.get('PriceTick', self.price_tick))
            self.exchange_id = ii.get('ExchangeID', self.exchange_id)
            self.spinBoxPrice.setSingleStep(self.price_tick)
            if self.parent:
                self.spinBoxPrice.setValue(self.parent.last_price)

    def buy_clicked(self):
        """开多"""
        symbol = self.comboBoxSymbol.currentText()
        price = self.spinBoxPrice.value()
        vol = self.spinBoxVol.value()
        data = OrderReq()

        data.price = price
        data.volume = vol
        data.symbol = symbol
        data.priceType = PRICETYPE_LIMITPRICE
        data.direction = CTP_DIRECTION_LONG
        data.offset = CTP_OFFSET_OPEN
        # msg = f'交易标的：{data.symbol}，价格：{data.price}，手数：{data.volume}，开多'
        # if not (QMessageBox.information(self, '交易信息', msg, QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Ok):
        #     return
        self._send_order(data)

    def short_clicked(self):
        """开空"""
        symbol = self.comboBoxSymbol.currentText()
        price = self.spinBoxPrice.value()
        vol = self.spinBoxVol.value()
        data = OrderReq()

        data.price = price
        data.volume = vol
        data.symbol = symbol
        data.priceType = PRICETYPE_LIMITPRICE
        data.direction = CTP_DIRECTION_SHORT
        data.offset = CTP_OFFSET_OPEN
        # msg = f'交易标的：{data.symbol}，价格：{data.price}，手数：{data.volume}，开空'
        # if not (QMessageBox.information(self, '交易信息', msg, QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Ok):
        #     return
        self._send_order(data)

    def sell_clicked(self):
        """平多"""
        symbol = self.comboBoxSymbol.currentText()
        price = self.spinBoxPrice.value()
        vol = self.spinBoxVol.value()
        data = OrderReq()

        data.price = price
        data.volume = vol
        data.symbol = symbol
        data.priceType = PRICETYPE_LIMITPRICE
        data.direction = CTP_DIRECTION_SHORT
        data.offset = CTP_OFFSET_CLOSE
        # msg = f'交易标的：{data.symbol}，价格：{data.price}，手数：{data.volume}，平多'
        # if not (QMessageBox.information(self, '交易信息', msg, QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Ok):
        #     return
        self._send_order(data)

    def cover_clicked(self):
        """平空"""
        symbol = self.comboBoxSymbol.currentText()
        price = self.spinBoxPrice.value()
        vol = self.spinBoxVol.value()
        data = OrderReq()
        data.price = price
        data.volume = vol
        data.symbol = symbol
        data.priceType = PRICETYPE_LIMITPRICE
        data.direction = CTP_DIRECTION_LONG
        data.offset = CTP_OFFSET_CLOSE
        # msg = f'交易标的：{data.symbol}，价格：{data.price}，手数：{data.volume}，平空'
        # if not (QMessageBox.information(self, '交易信息', msg, QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Ok):
        #     return
        self._send_order(data)

    def spinBoxPrice_valueChanged(self, e):
        # print(e)
        value = self.spinBoxPrice.value()
        # print(value, str(value))
        self.toolButtonBuy.setText(str(value) + '\n' + '开多')
        self.toolButtonShort.setText(str(value) + '\n' + '开空')
        self.toolButtonSell.setText(str(value) + '\n' + '平多')
        self.toolButtonCover.setText(str(value) + '\n' + '平空')

    def update_data(self, tick_event):
        """
        :param tick:
        :return:
        """
        tick = tick_event.dict_['data'].__dict__
        symbol = tick['InstrumentID']
        # print(symbol)
        if symbol == self.symbol:
            if self.pushButtonPriceType.text() != '指定价':
                self.spinBoxPrice.setValue(tick['LastPrice'])
                self.toolButtonBuy.setText(str(tick['AskPrice1']) + '\n' + '开多')
                self.toolButtonShort.setText(str(tick['BidPrice1']) + '\n' + '开空')
                self.toolButtonSell.setText(str(tick['AskPrice1']) + '\n' + '平多')
                self.toolButtonCover.setText(str(tick['BidPrice1']) + '\n' + '平空')

            self.labelSell.setText('卖:' + str(tick['AskPrice1']) + '/' + str(tick['AskVolume1']))
            self.labelBuy.setText('买:' + str(tick['BidPrice1']) + '/' + str(tick['BidVolume1']))
            self.labelUpper.setText('涨停:' + str(tick['UpperLimitPrice']))
            self.labelLower.setText('跌停:' + str(tick['LowerLimitPrice']))
            self.labelUpDown.setText('涨跌：' + str(tick['LastPrice'] - tick['PreSettlementPrice']))

    def order_clicked(self):
        """下单"""
        # if not self.symbol:
        #     return
        symbol = self.comboBoxSymbol.currentText()
        # if self.quote_event:
        #     self.quote_event.unregister(EVENT_TICK, self.update_data)
        price = self.spinBoxPrice.value()
        vol = self.spinBoxVol.value()

        order_req = OrderReq()
        if self.radioButtonSpeculation.isChecked():
            order_req.HedgeFlag = defineDict['THOST_FTDC_HF_Speculation']
        if self.radioButtonBuy.isChecked():
            order_req.direction = CTP_DIRECTION_LONG
        else:
            order_req.direction = CTP_DIRECTION_SHORT
        if self.radioButtonOpen.isChecked():
            order_req.offset = CTP_OFFSET_OPEN
        elif self.radioButtonCloseToday.isChecked():
            order_req.offset = CTP_OFFSET_CLOSETODAY
        elif self.radioButtonCloseYesterday.isChecked():
            order_req.offset = CTP_OFFSET_CLOSEYESTERDAY
        else:
            order_req.offset = CTP_OFFSET_CLOSE

        order_req.price = price
        order_req.volume = vol
        order_req.symbol = symbol
        order_req.priceType = PRICETYPE_LIMITPRICE
        self._send_order(order_req)

    def _send_order(self, data):
        msg = f'交易标的：{data.symbol}，价格：{data.price}，手数：{data.volume}，开平：{data.offset}，多空：{data.direction}'
        if QMessageBox.information(self, '交易信息', msg, QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Ok:
            if self.trade_event:
                # print(orderReq.__dict__)
                evnt = Event()
                evnt.event_type = EVENT_REQ_ORDER_INSERT
                evnt.dict_['data'] = data
                self.trade_event.put(evnt)
            self.sendOrderSignal.emit(data.__dict__)

    def pbPriceType_clicked(self):
        """价格来源点击事件"""
        if self.pushButtonPriceType.text() == '指定价':
            self.pushButtonPriceType.setText('市价')
            # if self.quote_event:
            #     self.quote_event.register(EVENT_TICK, self.update_data)
        else:
            self.pushButtonPriceType.setText('指定价')
            # if self.quote_event:
            #     self.quote_event.unregister(EVENT_TICK, self.update_data)


class StatUi(QMainWindow):
    """常用统计方法界面"""

    def __init__(self, *args):
        super(StatUi, self).__init__(*args)
        loadUi('uiStat.ui', self)  #
        self.pbFileName.clicked.connect(self.slotFile)
        self.pbLoadData.clicked.connect(self.slotLoadData)

    def slotFile(self):
        fileName1, filetype = QFileDialog.getOpenFileName(self,
                                                          "选取文件",
                                                          r"E:\Quant\notebook",
                                                          "All Files (*);;Text Files (*.txt)")
        self.leFileName.setText(fileName1)

    def slotLoadData(self):
        if self.leFileName.text() == '':
            self.slotFile()

        with open(self.leFileName.text(), 'rb') as f:
            df = pickle.load(f)
            df.index.stra_name = 'datetime'
            # print(df.columns.values)
            from utils.pandasModel import PandasModel
            mymodel = PandasModel(df)
            self.tableView.setModel(mymodel)

            # self.tableView.setModel(df)
            # self.datatable.setColumnCount(len(df.columns))
            # self.datatable.setRowCount(len(df.index))
            # print(len(df.columns),len(df.index))
            # for i in range(len(df.index)):
            #     for j in range(len(df.columns)):
            #         self.datatable.setItem(i, j, QTableWidgetItem(str(df.iget_value(i, j))))


class UITT(QMainWindow):
    """测试统一界面"""

    def __init__(self, parent=None, data_server=None, quote_event=None, trade_event=None, db_client=None, *args):
        super(UITT, self).__init__(*args)

        self.data_server = data_server
        self.quote_event = quote_event
        self.trade_event = trade_event
        self.db_client = db_client
        self._parent = parent

        self.setupUI()
        self.setWindowTitle('BoxQuant 投资管理系统')

    def setupUI(self):
        self.setObjectName("MainWindow")
        self.resize(1193, 786)
        self.setDockNestingEnabled(True)
        self.setDockOptions(
            QtWidgets.QMainWindow.AllowNestedDocks | QtWidgets.QMainWindow.AllowTabbedDocks | QtWidgets.QMainWindow.AnimatedDocks | QtWidgets.QMainWindow.ForceTabbedDocks | QtWidgets.QMainWindow.GroupedDragging | QtWidgets.QMainWindow.VerticalTabs)
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")
        self.centralLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.centralLayout.setContentsMargins(0, 0, 0, 0)
        self.centralLayout.setSpacing(0)
        self.centralLayout.setObjectName("centralLayout")
        self.setCentralWidget(self.centralwidget)
        self.dwLeft = QtWidgets.QDockWidget(self)
        self.dwLeft.setObjectName("dwLeft")
        self.dockWidgetContentsLeft = QtWidgets.QWidget()
        self.dockWidgetContentsLeft.setObjectName("dockWidgetContentsLeft")
        self.txtWidget = QtWidgets.QTextBrowser(parent=self.dockWidgetContentsLeft)

        self.dwLeft.setWidget(self.dockWidgetContentsLeft)
        self.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dwLeft)
        self.dwTop = QtWidgets.QDockWidget(self)
        self.dwTop.setObjectName("dwTop")
        self.dockWidgetContentsTop = QtWidgets.QWidget()
        self.dockWidgetContentsTop.setObjectName("dockWidgetContentsTop")
        self.dwTop.setWidget(self.dockWidgetContentsTop)
        self.addDockWidget(QtCore.Qt.DockWidgetArea(4), self.dwTop)
        self.dwBottom = QtWidgets.QDockWidget(self)
        self.dwBottom.setObjectName("dwBottom")
        self.dockWidgetContentsBottom = QtWidgets.QWidget()
        self.dockWidgetContentsBottom.setObjectName("dockWidgetContentsBottom")
        self.dwBottom.setWidget(self.dockWidgetContentsBottom)
        self.addDockWidget(QtCore.Qt.DockWidgetArea(8), self.dwBottom)
        self.dwRight = QtWidgets.QDockWidget(self)
        self.dwRight.setObjectName("dwRight")
        self.dockWidgetContentsRight = QtWidgets.QWidget()
        self.dockWidgetContentsRight.setObjectName("dockWidgetContentsRight")
        self.dwRight.setWidget(self.dockWidgetContentsRight)
        self.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.dwRight)

        self.pbTrade = QtWidgets.QPushButton('交易')
        self.pbTrade.clicked.connect(self.pbTrade_clicked)
        self.centralLayout.addWidget(self.pbTrade)
        self.pbAcc = QtWidgets.QPushButton('账户')
        self.pbAcc.clicked.connect(self.pbAcc_clicked)
        self.centralLayout.addWidget(self.pbAcc)
        self.pbQuote = QtWidgets.QPushButton('行情')
        self.pbQuote.clicked.connect(self.pbQuote_clicked)
        self.centralLayout.addWidget(self.pbQuote)
        self.pbBankInvestor = QtWidgets.QPushButton('转账')
        self.pbBankInvestor.clicked.connect(self.on_pbBankInvestor_clicked)
        self.centralLayout.addWidget(self.pbBankInvestor)

        self.pbTA = QtWidgets.QPushButton('技术分析')
        self.pbTA.clicked.connect(self.pbTA_clicked)
        self.centralLayout.addWidget(self.pbTA)
        self.pbDM = QtWidgets.QPushButton('数据管理')
        self.pbDM.clicked.connect(self.on_pbDM_clicked)
        self.centralLayout.addWidget(self.pbDM)
        self.pbSM = QtWidgets.QPushButton('策略监控')
        self.pbSM.clicked.connect(self.pbSM_clicked)
        self.centralLayout.addWidget(self.pbSM)
        self.pbSBT = QtWidgets.QPushButton('策略回测')
        self.pbSBT.clicked.connect(self.pbSBT_clicked)
        self.centralLayout.addWidget(self.pbSBT)

    def pbTA_clicked(self):
        """

        :return:
        """
        self._ta = TechAnalysis(quote_event=self.quote_event)
        self._ta.show()

    def pbSM_clicked(self):
        """

        :return:
        """
        self._sm = StrategyRunningMonitor()
        self._sm.show()

    def pbSBT_clicked(self):
        """

        :return:
        """
        self._sbt = StrategyBacktest()
        self._sbt.show()

    def pbQuote_clicked(self):
        self._quote_monitor = QuoteMonitor(quote_event_engine=self.quote_event)
        self._quote_monitor.show()

    def pbAcc_clicked(self):
        self._acc = AccountWidget(data_server=self.data_server, quote_event=self.quote_event,
                                  trade_event=self.trade_event)
        self._acc.show()

    def pbTrade_clicked(self):
        if self.quote_event and self.trade_event:
            importlib.reload(.frameOrder)
            self._order_pad = OrderPad(quote_event=self.quote_event, trade_event=self.trade_event)
            self._order_pad.show()

    def pb_clicked(self, sender):
        if sender:
            print(sender.stra_name)
        if sender == self.pbTrade:
            if self._order_pad:
                self._order_pad = .ui_child.OrderPad(parent=self, quote_event=self.quote_event_engine,
                                                           trade_event=self.trade_event_engine)
                self._order_pad.show()
            else:
                self._order_pad = .ui_child.OrderPad(parent=self, quote_event=self.quote_event_engine,
                                                           trade_event=self.trade_event_engine)
                self._order_pad.show()

    def on_pbDM_clicked(self):
        self.dm = DataManager(self.db_client, data_server=self.data_server)
        self.dm.show()

    def on_pbBankInvestor_clicked(self):
        self.wnd_bi = BankInvestor()
        # wnd = QtWidgets.QTextBrowser()
        # self.lo = QtWidgets.QHBoxLayout(self.dockWidgetContentsTop)
        # self.lo.addWidget(self.wnd_bi )
        # self.dwTop.setLayout(self.lo)
        # self.dwLef.setLayout(lo)
        self.wnd_bi.show()

    def get_data(self):
        if self.data_server:
            data = self.data_server.tick('ni1905')
            print(data)


class DataManager(DataManagerBase, Ui_DataManager):
    """数据管理器"""
    quote_servers = get_quote_server_dict()

    def __init__(self, db_client=None, data_server=None):
        super(DataManager, self).__init__()
        self.setupUi(self)  #
        self.initUI()

        self.data_server = data_server

        self.market_instrument_dict = IM.market_product_fut_dict

        if not db_client:
            self._db = DbHelper()
        else:
            self._db = db_client
        self.register_event()
        self._init_quote_server_table()
        self.register_widget_event()
        self.current_server_state = ''
        self._init_market_instrument_widget()

    def initUI(self):
        # set up the datetimeedit
        self.setWindowTitle('数据管理')
        self.dteEnd.setDateTime(QDateTime.currentDateTime())
        self.dteEnd.setDisplayFormat('yyyy-MM-dd HH:mm:ss')
        self.dteEnd.setCalendarPopup(True)
        self.dteStart.setDateTime(QDateTime.currentDateTime().addDays(-10))
        self.dteStart.setDisplayFormat('yyyy-MM-dd HH:mm:ss')
        self.dteStart.setCalendarPopup(True)
        self.deEndComp.setDateTime(QDateTime.currentDateTime())
        self.deEndComp.setDisplayFormat('yyyy-MM-dd HH:mm:ss')
        self.deEndComp.setCalendarPopup(True)
        self.deStartComp.setDateTime(QDateTime.currentDateTime().addDays(-10))
        self.deStartComp.setDisplayFormat('yyyy-MM-dd HH:mm:ss')
        self.deStartComp.setCalendarPopup(True)
        self.cbPeriodCom.addItems(period_zh_value_dict.keys())
        pass

    def register_widget_event(self):
        self.pbAddServer.clicked.connect(self.on_pbAddServer_clicked)
        self.pbSetAuto.clicked.connect(self.on_pbSetAuto_clicked)
        self.pbLink.clicked.connect(self.on_pbLink_clicked)
        self.pbDisconnect.clicked.connect(self.on_pbDisconnect_clicked)

        self.twQuoteServer.selectionChanged = self.on_twQuoteServer_selectionChanged

        self.cbSourceType.currentTextChanged = self.on_cbSourceType_currentTextChanged
        self.pbCSVFile.clicked = self.on_pbCSVFile_clicked

    def on_cbSourceType_currentTextChanged(self, txt):
        # print(txt)
        self.swDataSetting.setCurrentIndex(self.cbSourceType.currentIndex())

    def on_pbCSVFile_clicked(self):
        """"""
        fileName1, filetype = QFileDialog.getOpenFileName(self,
                                                          "选取文件",
                                                          '',
                                                          "All Files (*);;CSV Files (*.csv)")
        if not fileName1:
            return
        self.leCSVFile.setText(fileName1)

    def on_pbAddServer_clicked(self):
        """"""

    def on_pbSetAuto_clicked(self):
        """"""
        row_no = self.twQuoteServer.currentRow()
        col_no = 2  # 连接方式
        if self.twQuoteServer.item(row_no, col_no):
            self.current_server_state = self.twQuoteServer.item(row_no, col_no).text()
            if self.current_server_state == '自动':
                self.twQuoteServer.item(row_no, col_no).setText('手动')
                self.pbSetAuto.setText('设为自动')
            else:
                self.twQuoteServer.item(row_no, col_no).setText('自动')
                self.pbSetAuto.setText('设为手动')

    def on_pbLink_clicked(self):
        """"""

    def on_pbDisconnect_clicked(self):
        """"""

    def on_twQuoteServer_selectionChanged(self, selected, diselected):
        """"""
        row_no = self.twQuoteServer.currentRow()
        col_no = 2  # 连接方式
        if self.twQuoteServer.item(row_no, col_no):
            self.current_server_state = self.twQuoteServer.item(row_no, col_no).text()
            if self.current_server_state == '自动':
                self.pbSetAuto.setText('设为手动')
            else:
                self.pbSetAuto.setText('设为自动')

    def on_pbExec_clicked(self):
        sql = self.teSql.textCursor().selectedText()
        if not sql:
            sql = self.teSql.toPlainText()
        if not sql:
            return

        try:
            db = self.data_server.memdb
            df = pd.read_sql(sql, db)
            model = PandasModel(df)
            self.tblVResult.setModel(model)
            # print(df)
        except:
            pass
        # self.tblVResult
        # self.tbResult.clear()
        # self.tbResult.setText(*row)

    def _init_market_instrument_widget(self, market_instrument_dict=None):
        """初始化市场、标的信息"""
        if not market_instrument_dict:
            market_instrument_dict = self.market_instrument_dict
        # print('_init_market_instrument_widget', market_instrument_product_dict)
        if not market_instrument_dict:
            return
        tv = self.twMarketComp
        market = list(market_instrument_dict.keys())
        for itm in market:
            qtwi = QtWidgets.QTreeWidgetItem(tv)
            qtwi.setText(0, itm)

        if len(market) > 0:
            # print(type(market), market[0])
            exchnage_id = market[0]
            self.current_market_instrument = {'market': exchnage_id}
            lw=self.lwInstrumentComp
            lw.clear()
            product = list(market_instrument_dict[exchnage_id].keys())
            lw.headerItem().setText(0, exchnage_id)
            for itm in product:
                qtwi = QtWidgets.QTreeWidgetItem(lw)
                qtwi.setText(0, itm)
                for key in market_instrument_dict[exchnage_id][itm]:
                    # print('key:', key)
                    instrument = QtWidgets.QTreeWidgetItem(qtwi)
                    instrument.setText(0, key)
    def _init_quote_server_table(self):
        rc = 1
        tw = self.twQuoteServer
        quote_servers = self.quote_servers
        tw.setHorizontalHeaderLabels(['服务器名称', '状态', '连接方式', '速度'])
        for k, v in quote_servers.items():
            tw.setRowCount(rc)
            tw.setSpan(rc - 1, 0, 1, 4)  #
            twi0 = QtWidgets.QTableWidgetItem(k)
            tw.setItem(rc - 1, 0, twi0)
            rc += 1
            if v:
                for broker in v:
                    tw.setRowCount(rc)
                    broker_name = list(broker.keys())[0]
                    twi00 = QtWidgets.QTableWidgetItem(broker_name)
                    tw.setItem(rc - 1, 0, twi00)
                    twi01 = QtWidgets.QTableWidgetItem(broker[broker_name].get('auto', '手动'))
                    tw.setItem(rc - 1, 2, twi01)

                    rc += 1

    def _init_ui(self):
        """初始化 tree list combobox table"""

    def register_event(self):
        """注册窗口控件的相关事件"""


class StrategyRunningMonitor(StrategyRunningMonitorBase, Ui_StrategyRunningMonitor):
    """策略监控"""
    stra_types, stra_settings = get_strategy_setting()
    stra_typesI_list = list(stra_types.keys())
    stra_typesII_list = list(stra_types[INDICATOR_TYPE_TRADE_STRATEGY].keys())
    IID_COL = 2

    def __init__(self, strategies=None, params_dict=None, instruments=None, accounts=None, strategy_engine=None,
                 trade_event_engine=None, data_event_engine=None, db_client=None):
        super(StrategyRunningMonitor, self).__init__()
        self.setupUi(self)
        self.setWindowTitle('策略运行监控')
        self.current_stra_no = 0  # 当前策略序号
        self._strategies = strategies
        self._params_dict = params_dict
        self._instruments = instruments
        self.db_client = db_client
        self.market_instrument_dict = load_future_market_product(db_client=self.db_client)
        mpiid = {}
        for k, v in self.market_instrument_dict.items():
            mpiid[k] = {}
            for k1, v1 in v.items():
                mpiid[k][k1] = list(v1.keys())
        self._accounts = accounts
        self.strategy_engine = strategy_engine
        self.trade_event_engine = trade_event_engine
        self.data_event_engine = data_event_engine
        self._init_strategy_tree()

        self.instrument_selector = ThreeListWidget(data=mpiid,
                                                   direction=1)  # loadUi(path.join(pyqt_ui_path, 'three_list_widget.ui'))  # Ui_ThreeListWidget()
        # self.instrument_selector.setupUi(self.instrument_selector)
        # self._init_market_instrument_widget()

        self._register_widgets_event()

        self.cc = 0

    def _register_widgets_event(self):
        """注册控件事件"""
        self.twStrategy.itemDoubleClicked.connect(self._twStrategy_itemDoubleClicked)
        self.twStrategyInstance.itemDoubleClicked.connect(self._twStrategyInstance_itemClicked)
        self.twStartedStrategy.cellClicked.connect(self.twStartedStrategy_cellClicked)
        self.instrument_selector.lw3.itemClicked.connect(self.instrument_selector_lw3_itemClicked)

        # button 事件
        self.pbSaveStrategyParams.mouseReleaseEvent = self.on_pbSaveStrategyParams_clicked
        self.pbStrategyInit.mouseReleaseEvent = self.on_pbStrategyInit_clicked
        self.pbStrategyStart.mouseReleaseEvent = self.on_pbStrategyStart_clicked
        self.pbStrategyStop.mouseReleaseEvent = self.on_pbStrategyStop_clicked

    def on_pbSaveStrategyParams_clicked(self, e):
        print('on_pbSaveStrategyParams_clicked')
        self.cc += 1
        print(self.cc)

    def on_pbStrategyInit_clicked(self, e):
        print(e.__dict__)
        print('on_pbStrategyInit_clicked')

    def on_pbStrategyStart_clicked(self, e):
        print('on_pbStrategyStart_clicked')
        self.cc += 1
        print(self.cc)

    def on_pbStrategyStop_clicked(self, e):
        print('on_pbStrategyStop_clicked')
        self.cc += 1
        print(self.cc)

    def set_settings(self, strategies, params_dict, instruments, accounts):
        self._strategies = strategies
        self._params_dict = params_dict
        self._instruments = instruments
        self._accounts = accounts

    def _init_strategy_tree(self):
        """
        用策略分类、实例名称、参数初始化策略分类树、实例树、参数列表
        :return:
        """
        # indicator = self.system_conf['技术指标']
        stra = self.stra_types  # .system_conf['交易策略']
        # print(ss)
        self.strategy_setting = {}
        self.strategy_param_dict = {}
        self.strategy_class_dict = {}
        # 策略分类
        tws = self.twStrategy
        tws.clear()

        for key, val in stra.items():  # 策略分组
            qtwi = QtWidgets.QTreeWidgetItem(tws)
            qtwi.setText(0, key)
            # print(val)
            for k, v in val.items():  # 策略类型
                itm0 = QtWidgets.QTreeWidgetItem(qtwi)
                itm0.setText(0, k)
                self.strategy_class_dict['.'.join([key, k])] = v

        # 策略实例
        headertext = '.'.join([INDICATOR_TYPE_TRADE_STRATEGY, self.stra_typesII_list[0]])
        self.current_strategy_class_name = self.stra_typesI_list[0]
        twsi = self.twStrategyInstance
        twsi.headerItem().setText(0, headertext)
        twsi.clear()
        scin = ''
        for itm in self.strategy_class_dict[headertext]:
            qtwi = QtWidgets.QTreeWidgetItem(twsi)
            qtwi.setText(0, itm)
            for k, v in self.stra_settings.items():
                if itm in k:
                    qtwi0 = QtWidgets.QTreeWidgetItem(qtwi)
                    qtwi0.setText(0, k)
                    scin = k
        # 实例参数
        if scin:
            self.current_strategy_instance_name = scin
            if 'params' in self.stra_settings[scin].keys():
                cur_param = self.stra_settings[scin]['params']
                tw = self.twParams
                tw.clearContents()
                i = 0  # tw的行序号
                j = 0  # 列序号：名称，缺省，最小，最大，步长，乘数，说明
                tw.setRowCount(len(cur_param))
                for k, v in cur_param.items():
                    j = 0
                    itm = QtWidgets.QTableWidgetItem(k)  # 参数名称
                    tw.setItem(i, j, itm)
                    # print(v)
                    try:
                        j += 1
                        pvitm = QtWidgets.QTableWidgetItem(str(v['default']))
                        tw.setItem(i, j, pvitm)
                        j += 1
                        pvitm = QtWidgets.QTableWidgetItem(str(v['min']))
                        tw.setItem(i, j, pvitm)
                        j += 1
                        pvitm = QtWidgets.QTableWidgetItem(str(v['max']))
                        tw.setItem(i, j, pvitm)
                        j += 1
                        pvitm = QtWidgets.QTableWidgetItem(str(v['step']))
                        tw.setItem(i, j, pvitm)
                        j += 1
                        pvitm = QtWidgets.QTableWidgetItem(str(v['multiplier']))
                        tw.setItem(i, j, pvitm)
                        j += 1
                        pvitm = QtWidgets.QTableWidgetItem(str(v['description']))
                        tw.setItem(i, j, pvitm)

                    except KeyError:
                        pass
                    i += 1

    def _twStrategy_itemDoubleClicked(self, item, col):
        """策略分类 树单击事件"""
        if item.childCount() == 0:
            if not item.parent(): return
            scn = item.text(0)  # 策略、指标分类名称
            headertext = '.'.join([item.parent().text(0), scn])
            twi = self.twStrategyInstance
            twi.headerItem().setText(0, headertext)
            twi.clear()
            for itm in self.strategy_class_dict[headertext]:
                qtwi = QtWidgets.QTreeWidgetItem(twi)
                qtwi.setText(0, itm)
                for k, v in self.stra_settings.items():
                    if itm in k:
                        qtwi0 = QtWidgets.QTreeWidgetItem(qtwi)
                        qtwi0.setText(0, k)

    def _twStrategyInstance_itemClicked(self, item, col):
        """策略实例点击事件"""
        # print(self.stra_settings)
        tw = self.twParams
        tw.clearContents()
        self.current_strategy_class_name = item.text(0)
        if item.childCount() == 0:
            scin = item.text(0)  # 策略、指标实例名称
            if item.parent():
                self.current_strategy_class_name = item.parent().text(0)
            if scin in self.stra_settings.keys():
                self.current_strategy_instance_name = scin
                if 'params' in self.stra_settings[scin].keys():
                    cur_param = self.stra_settings[scin]['params']

                    i = 0  # tw的行序号
                    j = 0  # 列序号：名称，缺省，最小，最大，步长，乘数，说明
                    tw.setRowCount(len(cur_param))
                    for k, v in cur_param.items():
                        j = 0
                        itm = QtWidgets.QTableWidgetItem(k)  # 参数名称
                        tw.setItem(i, j, itm)
                        # print(v)
                        try:
                            j += 1
                            pvitm = QtWidgets.QTableWidgetItem(str(v['default']))
                            tw.setItem(i, j, pvitm)
                            j += 1
                            pvitm = QtWidgets.QTableWidgetItem(str(v['min']))
                            tw.setItem(i, j, pvitm)
                            j += 1
                            pvitm = QtWidgets.QTableWidgetItem(str(v['max']))
                            tw.setItem(i, j, pvitm)
                            j += 1
                            pvitm = QtWidgets.QTableWidgetItem(str(v['step']))
                            tw.setItem(i, j, pvitm)
                            j += 1
                            pvitm = QtWidgets.QTableWidgetItem(str(v['multiplier']))
                            tw.setItem(i, j, pvitm)
                            j += 1
                            pvitm = QtWidgets.QTableWidgetItem(str(v['description']))
                            tw.setItem(i, j, pvitm)

                        except KeyError:
                            pass
                        i += 1

    def _init_market_instrument_widget(self, market_instrument_dict=None):
        """初始化市场、标的信息"""
        if not market_instrument_dict:
            market_instrument_dict = self.market_instrument_dict
        # print('_init_market_instrument_widget', market_instrument_product_dict)
        if not market_instrument_dict:
            return
        lw1 = self.instrument_selector.lw1
        market = list(market_instrument_dict.keys())
        lw1.addItems(market)

        if len(market) > 0:
            # print(type(market), market[0])
            lw2 = self.instrument_selector.lw2
            lw2.clear()
            exchnage_id = market[0]
            product = list(market_instrument_dict[exchnage_id].keys())
            lw2.addItems(product)
            lw3 = self.instrument_selector.lw3
            lw3.clear()
            # print(market_instrument_dict[exchnage_id][product[0]])
            if len(product):
                iid = list(market_instrument_dict[exchnage_id][product[0]].keys())
                lw3.addItems(iid)

    def _tvMarket_itemClicked(self, item, col):
        """market tree_item clicked"""
        if item.childCount() == 0:
            exchnage_id = item.text(0)
            self.current_market_instrument = {'market': exchnage_id}
            self.lvInstruments.clear()
            product = list(self.market_instrument_dict[exchnage_id].keys())
            self.lvInstruments.headerItem().setText(0, exchnage_id)
            for itm in product:
                qtwi = QtWidgets.QTreeWidgetItem(self.lvInstruments)
                qtwi.setText(0, itm)
                for key in self.market_instrument_dict[exchnage_id][itm]:
                    # print('key:', key)
                    instrument = QtWidgets.QTreeWidgetItem(qtwi)
                    instrument.setText(0, key)

    def _lvInstruments_itemClicked(self, item, col):
        if item.childCount() == 0:
            self.current_market_instrument['instrument'] = item.text(0)
            self.lstwInstrument.clear()
            self.lstwInstrument.addItems([item.text(0)])
            self.symbol = item.text(0)

    def twStartedStrategy_cellClicked(self, x, y):
        """"""
        # print(x, y)
        self.current_stra_no = x
        if y == self.IID_COL:
            self.instrument_selector.show()
        else:
            self.instrument_selector.hide()
            # iid = self.instrument_selector.lw3.selectedItems()[0].text()
            # print(iid)

    def instrument_selector_lw3_itemClicked(self, e):
        iid = self.instrument_selector.lw3.selectedItems()[0].text()
        # print(self.twStartedStrategy.rowCount(), e.text())
        # print(self.twStartedStrategy.currentItem())
        if self.twStartedStrategy.rowCount() == 0:
            self.twStartedStrategy.setRowCount(1)
        if not self.twStartedStrategy.currentItem():
            itw = QtWidgets.QTableWidgetItem()
            itw.setText(iid)
            self.twStartedStrategy.setItem(self.current_stra_no, self.IID_COL, itw)
        else:
            self.twStartedStrategy.currentItem().setText(iid)
        # print(iid)
        # self.twStartedStrategy.currentItem().setText(iid)


from strategy.strategy_setting import get_result_display_items_dict


class StrategyBacktest(StrategyBacktestBase, Ui_StrategyBacktest):
    """策略回测界面"""

    stra_types, stra_settings = get_strategy_setting()
    stra_typesI_list = list(stra_types.keys())
    stra_typesII_list = list(stra_types[INDICATOR_TYPE_TRADE_STRATEGY].keys())

    # 回测结果总览
    result_overview = {"策略分析":
                           ["概览",
                            "收益风险分析",
                            "时间仓位分析",
                            "资产曲线",
                            "资产与回撤曲线",
                            "资产升水与回撤曲线",
                            "资产升水与回撤幅度曲线"],
                       "交易分析":
                           ["交易明细",
                            "交易总体分析",
                            "连续盈亏分析",
                            "离群分析",
                            "最大浮盈浮亏",
                            "平仓收益曲线",
                            "平仓收益曲线与回撤图",
                            "多头平仓收益曲线与回撤图",
                            "空头平仓收益曲线与回撤图",
                            "平仓盈亏散点图",
                            "有效盈亏率散点图",
                            "平仓盈亏分布图",
                            "最大浮盈散点图",
                            "最大浮盈-平仓盈亏柱状图",
                            "最大浮盈-平仓盈亏散点图",
                            "最大浮亏散点图",
                            "最大浮亏-平仓盈亏柱状图",
                            "最大浮亏-平仓盈亏散点图"],
                       "时段分析":
                           ["日交易分析",
                            "周交易分析",
                            "月绩效分析",
                            "月度分析",
                            "年度分析",
                            "月净值收益与回撤柱形图",
                            "月净值收益与回撤柱幅度形图",
                            "月平仓收益与回撤柱形图",
                            "月平仓收益与回撤幅度柱形图"]
                       }

    def __init__(self, db_client=None, data_engine=None):
        super(StrategyBacktest, self).__init__()
        # importlib.reload(base.strategy_engine)
        self.test_engine = StraEE.StraBTEngine(db_client=db_client)
        self.data_engine = data_engine
        self.setupUi(self)
        self.setWindowTitle('策略回测')
        self.db_client = db_client
        # self.market_instrument_dict = market_instrument
        # if market_instrument is None:
        self.market_instrument_dict = IM.market_product_fut_dict  # load_future_market_product(db_client=self.db_client)
        self._register_widgets_event()
        self._init_strategy_tree()
        self._init_market_instrument_widget()
        self.current_market_instrument = {}
        self.symbol = ''
        self.display_items = get_result_display_items_dict()

        self._init_tables()

        self.cbbTestPeriod.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents)

        self.data = None

        self.tabWidgetMarket.setCurrentWidget(self.tabOpenSignal)

    def _register_widgets_event(self):
        """注册控件事件"""
        self.dteTestEnd.setDate(QtCore.QDate.currentDate().addDays(1))
        self.dteTestStart.setDate(QtCore.QDate.currentDate().addDays(-20))
        # 指标分类点击事件
        self.twIndicatorClass.itemClicked.connect(self._twIndicatorClass_itemClicked)
        self.twIndicators.itemClicked.connect(self._twIndicator_itemClicked)

        self.tvMarket.itemClicked.connect(self._tvMarket_itemClicked)
        self.lvInstruments.itemClicked.connect(self._lvInstruments_itemClicked)
        # 测试报告项目点击事件
        self.tw_report_items.itemClicked.connect(self.report_items_itemClicked)
        # 新建指标、策略按钮点击事件
        self.pbNew.clicked.connect(self.pbNew_clicked)
        # 开始测试按钮点击事件
        self.tbStart.clicked.connect(self.tbStart_clicked)
        self.tbLoad.clicked.connect(self.tbLoad_clicked)
        self.tbSave.clicked.connect(self.tbSave_clicked)
        self.tbOptimise.clicked.connect(self.tbOptimise_clicked)

        self.test_engine.register(EVENT_BACKTEST_RESULT, self._fill_backtest_result)

    def _init_tables(self):
        """初始化相关表格"""
        # 设置[策略回测报告项目]列表
        tw = self.tw_report_items
        tw.clear()
        for k, v in self.result_overview.items():
            pw = QtWidgets.QTreeWidgetItem(tw)
            pw.setText(0, k)
            for itm in v:
                cw = QtWidgets.QTreeWidgetItem(pw)
                cw.setText(0, itm)

        # 设置[总体概要]的表格内容
        tbl = self.tableReportSummary
        itms = self.display_items['总体概要']
        max_no = max([itm['no.'] for itm in itms])
        itms1 = self.display_items['测试设置']
        max_no1 = max([itm['no.'] for itm in itms1])
        tbl.setRowCount(max_no + max_no1 + 2)
        for itm in itms:
            tblwi = QtWidgets.QTableWidgetItem(itm['cn'])
            tbl.setItem(itm['no.'] - 1, 0, tblwi)
        tblwi = QtWidgets.QTableWidgetItem('测试设置')
        rn = max_no + 1
        tbl.setItem(rn, 0, tblwi)
        tbl.setSpan(rn, 0, 1, 4)
        for itm in itms1:
            tblwi = QtWidgets.QTableWidgetItem(itm['cn'])
            rn = max_no + itm['no.'] + 1
            tbl.setItem(rn, 0, tblwi)
            tbl.setSpan(rn, 1, 1, 3)

        # 设置[交易明细]的表格内容
        tbl = self.tableTradeDetail
        itms = self.display_items['交易明细']
        cn = [itm['cn'] for itm in itms]
        tbl.setColumnCount(len(itms))  # 设置列数量
        tbl.setHorizontalHeaderLabels(cn)  # 设置列表头

    def tbSave_clicked(self):
        """保存测试结果"""

    def tbLoad_clicked(self):
        """调入测试结果"""
        print(self.stra_settings.keys())
        print(self.stra_settings)

    def tbStart_clicked(self):
        """开始测试
        从界面取得策略类名、参数值、周期、开始日期、结束日期、费率及"""
        # print("""创建并初始化策略""")
        # print(self.current_strategy_instance_name)
        # print(self.current_strategy_class_name)
        start_datetime = self.dteTestStart.text().replace('-', '')
        end_datetime = self.dteTestEnd.text().replace('-', '')
        period_zh = self.cbbTestPeriod.currentText()
        period_en = period_zh_en_dict[period_zh]
        period = period_zh_value_dict[period_zh]

        # print(start_datetime, type(end_datetime), period)
        params = {}
        i = 0
        tbl = self.tblTestParams
        while i < tbl.rowCount():
            params[tbl.item(i, 0).text()] = eval(tbl.item(i, 1).text())
            i += 1
        print(params, self.symbol)
        symbol = self.symbol  # 'jm1905'
        scn = self.current_strategy_class_name  # 'TrendStrategy'
        si_id = '_'.join([scn, symbol, str(period)])
        self.test_engine.register(EVENT_BACKTEST_RESULT + si_id, self._fill_backtest_result)
        rslt = self.test_engine.run(scn, symbol, start_datetime, end_datetime, params,
                                    period=period)
        # print(rslt)

    def _fill_backtest_result(self, event):
        ddct = event.dict_
        # print(ddct.keys())
        data = ddct['data']
        self.data = data
        lr = data['long']
        sr = data['short']
        # import .ui_tools.fill_backtest_result
        # importlib.reload(.ui_tools.fill_backtest_result)
        # .ui_tools.fill_backtest_result.fill_backtest_result(self.stackedWidgetReport, data=data)
        w = self.stackedWidgetReport
        ttr = self.tableReportSummary
        tbl = self.tableReportSummary
        itms = self.display_items['总体概要']
        max_no = max([itm['no.'] for itm in itms])
        # print(lr.__dict__)
        for itm in itms:
            if lr and itm['en'] in lr.__dict__.keys() and lr.__dict__[itm['en']] is not None:
                tblwi = QtWidgets.QTableWidgetItem(str(safe_unicode(lr.__dict__[itm['en']])))
                tbl.setItem(itm['no.'] - 1, 1, tblwi)
            if sr and itm['en'] in sr.__dict__.keys() and sr.__dict__[itm['en']] is not None:
                tblwi = QtWidgets.QTableWidgetItem(str(safe_unicode(sr.__dict__[itm['en']])))
                tbl.setItem(itm['no.'] - 1, 2, tblwi)
        itms = self.display_items['测试设置']
        for itm in itms:
            # print(itm['en'])
            if itm['en'] in ddct.keys():
                tblwi = QtWidgets.QTableWidgetItem(str(ddct[itm['en']]))
                tbl.setItem(max_no + itm['no.'] + 1, 1, tblwi)
        # ttr.setColumnCount(4)
        # ttr.setHorizontalHeader()

    def plot_(self,data):
        vl = self.vl_tmp
        # date_axis = pg.graphicsItems.DateAxisItem.DateAxisItem(orientation='bottom')
        # self.graph = pg.PlotWidget(axisItems={'bottom': date_axis})
        pw = pg.PlotWidget(enableAutoRange=True)
        vl.addWidget(pw)
        p1 = pw.plot()
        p1.setPen((200, 200, 100))
        dd = data.td_nv
        p1.setData(dd)
        # print(dd)
        pw.setLabel('left', 'Value', units='V')
        pw.setLabel('bottom', 'Time', units='s')

    def tbOptimise_clicked(self):
        """参数优化"""

    def pbNew_clicked(self):
        importlib.reload(.newclicked)
        .newclicked.newclicked('box ro')

    def _init_strategy_tree(self):
        """
        用策略分类、实例名称、参数初始化策略分类树、实例树、参数列表
        :return:
        """
        # indicator = self.system_conf['技术指标']
        stra = self.stra_types  # .system_conf['交易策略']
        # print(ss)
        self.strategy_setting = {}
        self.strategy_param_dict = {}
        self.strategy_class_dict = {}
        # 策略分类
        self.twIndicatorClass.clear()

        for key, val in stra.items():  # 策略分组
            qtwi = QtWidgets.QTreeWidgetItem(self.twIndicatorClass)
            qtwi.setText(0, key)
            # print(val)
            for k, v in val.items():  # 策略类型
                itm0 = QtWidgets.QTreeWidgetItem(qtwi)
                itm0.setText(0, k)
                self.strategy_class_dict['.'.join([key, k])] = v

        # 策略实例
        headertext = '.'.join([INDICATOR_TYPE_TRADE_STRATEGY, self.stra_typesII_list[0]])
        self.current_strategy_class_name = self.stra_typesI_list[0]
        self.twIndicators.headerItem().setText(0, headertext)
        self.twIndicators.clear()
        scin = ''
        for itm in self.strategy_class_dict[headertext]:
            qtwi = QtWidgets.QTreeWidgetItem(self.twIndicators)
            qtwi.setText(0, itm)
            for k, v in self.stra_settings.items():
                if itm in k:
                    qtwi0 = QtWidgets.QTreeWidgetItem(qtwi)
                    qtwi0.setText(0, k)
                    scin = k
        # 实例参数
        if scin:
            self.current_strategy_instance_name = scin
            if 'params' in self.stra_settings[scin].keys():
                cur_param = self.stra_settings[scin]['params']
                tw = self.tblTestParams
                tw.clearContents()
                i = 0  # tw的行序号
                j = 0  # 列序号：名称，缺省，最小，最大，步长，乘数，说明
                tw.setRowCount(len(cur_param))
                for k, v in cur_param.items():
                    j = 0
                    itm = QtWidgets.QTableWidgetItem(k)  # 参数名称
                    tw.setItem(i, j, itm)
                    # print(v)
                    try:
                        j += 1
                        pvitm = QtWidgets.QTableWidgetItem(str(v['default']))
                        tw.setItem(i, j, pvitm)
                        j += 1
                        pvitm = QtWidgets.QTableWidgetItem(str(v['min']))
                        tw.setItem(i, j, pvitm)
                        j += 1
                        pvitm = QtWidgets.QTableWidgetItem(str(v['max']))
                        tw.setItem(i, j, pvitm)
                        j += 1
                        pvitm = QtWidgets.QTableWidgetItem(str(v['step']))
                        tw.setItem(i, j, pvitm)
                        j += 1
                        pvitm = QtWidgets.QTableWidgetItem(str(v['multiplier']))
                        tw.setItem(i, j, pvitm)
                        j += 1
                        pvitm = QtWidgets.QTableWidgetItem(str(v['description']))
                        tw.setItem(i, j, pvitm)

                    except KeyError:
                        pass
                    i += 1
        # 初始化测试周期
        self.cbbTestPeriod.addItems(period_en_zh_dict.values())
        self.cbbTestPeriod.setCurrentIndex(1)

    def _twIndicatorClass_itemClicked(self, item, col):
        """策略分类 树单击事件"""
        if item.childCount() == 0:
            if not item.parent(): return
            scn = item.text(0)  # 策略、指标分类名称
            headertext = '.'.join([item.parent().text(0), scn])
            self.twIndicators.headerItem().setText(0, headertext)
            self.twIndicators.clear()
            for itm in self.strategy_class_dict[headertext]:
                qtwi = QtWidgets.QTreeWidgetItem(self.twIndicators)
                qtwi.setText(0, itm)
                for k, v in self.stra_settings.items():
                    if itm in k:
                        qtwi0 = QtWidgets.QTreeWidgetItem(qtwi)
                        qtwi0.setText(0, k)

    def _twIndicator_itemClicked(self, item, col):
        """策略实例点击事件"""
        # print(self.stra_settings)
        tw = self.tblTestParams
        tw.clearContents()
        self.current_strategy_class_name = item.text(0)
        if item.childCount() == 0:
            scin = item.text(0)  # 策略、指标实例名称
            if item.parent():
                self.current_strategy_class_name = item.parent().text(0)
            if scin in self.stra_settings.keys():
                self.current_strategy_instance_name = scin
                if 'params' in self.stra_settings[scin].keys():
                    cur_param = self.stra_settings[scin]['params']

                    i = 0  # tw的行序号
                    j = 0  # 列序号：名称，缺省，最小，最大，步长，乘数，说明
                    tw.setRowCount(len(cur_param))
                    for k, v in cur_param.items():
                        j = 0
                        itm = QtWidgets.QTableWidgetItem(k)  # 参数名称
                        tw.setItem(i, j, itm)
                        # print(v)
                        try:
                            j += 1
                            pvitm = QtWidgets.QTableWidgetItem(str(v['default']))
                            tw.setItem(i, j, pvitm)
                            j += 1
                            pvitm = QtWidgets.QTableWidgetItem(str(v['min']))
                            tw.setItem(i, j, pvitm)
                            j += 1
                            pvitm = QtWidgets.QTableWidgetItem(str(v['max']))
                            tw.setItem(i, j, pvitm)
                            j += 1
                            pvitm = QtWidgets.QTableWidgetItem(str(v['step']))
                            tw.setItem(i, j, pvitm)
                            j += 1
                            pvitm = QtWidgets.QTableWidgetItem(str(v['multiplier']))
                            tw.setItem(i, j, pvitm)
                            j += 1
                            pvitm = QtWidgets.QTableWidgetItem(str(v['description']))
                            tw.setItem(i, j, pvitm)

                        except KeyError:
                            pass
                        i += 1

    def report_items_itemClicked(self, item, col):
        if item.text(0) == '概览':
            self.stackedWidgetReport.setCurrentWidget(self.pgSummary)
        elif item.text(0) == '收益风险分析':
            self.stackedWidgetReport.setCurrentWidget(self.pgRiskReturnAnalysis)
        elif item.text(0) == '时间仓位分析':
            self.stackedWidgetReport.setCurrentWidget(self.pgTimePositionAnalysis)
        elif item.text(0) == '资产曲线':
            self.stackedWidgetReport.setCurrentWidget(self.page_asset_curve)
        elif item.text(0) == '平仓收益曲线':
            self.stackedWidgetReport.setCurrentWidget(self.pg_tmp)
            if self.data is not None:
                # self.data['long'].td_nv.plot.line()
                self.plot_(self.data['long'])
            # self.stackedWidgetReport.setCurrentWidget(self.page_close_profit_line)

        elif item.text(0) == '资产升水与回撤幅度曲线':
            self.stackedWidgetReport.setCurrentWidget(self.page_asset_rise_pct)
        elif item.text(0) == '资产升水与回撤曲线':
            self.stackedWidgetReport.setCurrentWidget(self.page_asset_rise)
        elif item.text(0) == '资产与回撤曲线':
            self.stackedWidgetReport.setCurrentWidget(self.page_asset_down_curve)
        elif item.text(0) == '交易明细':
            self.stackedWidgetReport.setCurrentWidget(self.page_trade_detail)

    def _init_market_instrument_widget(self, market_instrument_dict=None):
        """初始化市场、标的信息"""
        if not market_instrument_dict:
            market_instrument_dict = self.market_instrument_dict
        # print('_init_market_instrument_widget', market_instrument_product_dict)
        if not market_instrument_dict:
            return
        tv = self.tvMarket
        market = list(market_instrument_dict.keys())
        for itm in market:
            qtwi = QtWidgets.QTreeWidgetItem(tv)
            qtwi.setText(0, itm)

        if len(market) > 0:
            # print(type(market), market[0])
            exchnage_id = market[0]
            self.current_market_instrument = {'market': exchnage_id}
            self.lvInstruments.clear()
            product = list(market_instrument_dict[exchnage_id].keys())
            self.lvInstruments.headerItem().setText(0, exchnage_id)
            for itm in product:
                qtwi = QtWidgets.QTreeWidgetItem(self.lvInstruments)
                qtwi.setText(0, itm)
                for key in market_instrument_dict[exchnage_id][itm]:
                    # print('key:', key)
                    instrument = QtWidgets.QTreeWidgetItem(qtwi)
                    instrument.setText(0, key)

    def _tvMarket_itemClicked(self, item, col):
        """market tree_item clicked"""
        if item.childCount() == 0:
            exchnage_id = item.text(0)
            self.current_market_instrument = {'market': exchnage_id}
            self.lvInstruments.clear()
            product = list(self.market_instrument_dict[exchnage_id].keys())
            self.lvInstruments.headerItem().setText(0, exchnage_id)
            for itm in product:
                qtwi = QtWidgets.QTreeWidgetItem(self.lvInstruments)
                qtwi.setText(0, itm)
                for key in self.market_instrument_dict[exchnage_id][itm]:
                    # print('key:', key)
                    instrument = QtWidgets.QTreeWidgetItem(qtwi)
                    instrument.setText(0, key)

    def _lvInstruments_itemClicked(self, item, col):
        if item.childCount() == 0:
            self.current_market_instrument['instrument'] = item.text(0)
            self.lstwInstrument.clear()
            self.lstwInstrument.addItems([item.text(0)])
            self.symbol = item.text(0)

    def closeEvent(self, event):
        reply = QtWidgets.QMessageBox.question(self, '退出',
                                               '确认退出?', QtWidgets.QMessageBox.Yes |
                                               QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.Yes)
        if reply == QtWidgets.QMessageBox.Yes:
            self.test_engine.close_price()
            event.accept()
        else:
            event.ignore()


class FormulaEditor(FormulaEditorBase, Ui_FormulaEditor):
    """公式编辑器"""

    def __init__(self):
        super(FormulaEditor, self).__init__()
        self.setupUi(self)


class AccountWidget(AccountBase, Ui_DockWidgetAccount):
    """账户管理器"""

    def __init__(self, parent=None, data_server=None, quote_event=None, trade_event=None, db_client=None,
                 account_server=None, event_type: dict = None, *args):
        super(AccountWidget, self).__init__()
        self.setupUi(self)
        self.event_type = event_type
        if not event_type:
            self.event_type = {'account': EVENT_RSP_ACCOUNT, 'position': EVENT_RSP_POSITION,
                               'position_detail': EVENT_RSP_POSITION_DETAIL, 'trade': EVENT_RTN_TRADE,
                               'order': EVENT_RTN_ORDER}
        self.setWindowTitle('账户管理')
        self.data_server = data_server
        self.quote_event = quote_event
        self.trade_event_engine = trade_event
        self.account_event = trade_event
        self.account_server = account_server
        self.db_client = db_client
        self._parent = parent
        if parent:
            self.account_server = parent.account_server

        self._create_account_tables()
        self.register_widget_events()

    def _create_account_tables(self):
        """创建账户相关表格"""
        print(self.event_type)
        self.accountTable = AccountMonitor(account_engine=self.account_server,
                                           account_event=self.trade_event_engine,
                                           event_type=self.event_type['account'])
        self.accountTableLayout = QtWidgets.QVBoxLayout(self.tabAccount)
        self.accountTableLayout.setObjectName('accountTableLayout')
        self.accountTableLayout.addWidget(self.accountTable)
        # 委托-下单表格
        self.orderTable = OrderMonitor(account_engine=self.account_server, account_event=self.trade_event_engine
                                       , event_type=self.event_type['order'])
        self.orderTableLayout = QtWidgets.QVBoxLayout(self.tabOrder)
        self.orderTableLayout.setObjectName('orderTableLayout')
        self.orderTableLayout.addWidget(self.orderTable)
        # 预埋单表格 twOrder=QtWidgets.QTabWidget()
        # self.tabPreOrder = QtWidgets.QWidget()
        # self.tabPreOrder.setObjectName("tabPreOrder")
        # self.twOrder.addTab(self.tabPreOrder, "预埋委托单")
        # self.porderTable = PreOrderMonitor(account_engine=self.account_server, account_event=self.trade_event_engine
        #                                    )
        # self.porderTableLayout = QtWidgets.QVBoxLayout(self.tabPreOrder)
        # self.porderTableLayout.setObjectName('porderTableLayout')
        # self.porderTableLayout.addWidget(self.porderTable)

        # 成交表格
        self.tradeTable = TradeMonitor(account_engine=self.account_server, account_event=self.trade_event_engine,
                                       event_type=self.event_type['trade'])
        self.tradeTableLayout = QtWidgets.QVBoxLayout(self.tabTraded)
        self.tradeTableLayout.setObjectName('tradeTableLayout')
        self.tradeTableLayout.addWidget(self.tradeTable)
        # self.tradeTable.set_account_event_type(self.event_type['trade'])
        # 未成交委托表格
        self.untradeTable = UTOrderMonitor(account_engine=self.account_server, account_event=self.trade_event_engine)
        self.untradeTableLayout = QtWidgets.QVBoxLayout(self.tabUntrade)
        self.untradeTableLayout.setObjectName('untradeTableLayout')
        self.untradeTableLayout.addWidget(self.untradeTable)
        # 持仓表格
        self.positionTable = PositionMonitor(account_engine=self.account_server, account_event=self.trade_event_engine,
                                             event_type=self.event_type['position'])
        self.positionTableLayout = QtWidgets.QVBoxLayout(self.tabAccountPosition)
        self.positionTableLayout.setObjectName('positionTableLayout')
        self.positionTableLayout.addWidget(self.positionTable)
        # self.positionTable.set_account_event_type(self.event_type['position'])

        # 持仓明细表格
        self.positionDetailTable = PositionDetailMonitor(account_engine=self.account_server,
                                                         account_event=self.trade_event_engine,
                                                         event_type=self.event_type['position_detail'])
        self.positionDetailTableLayout = QtWidgets.QVBoxLayout(self.tabPostionDetail)
        self.positionDetailTableLayout.setObjectName('positionDetailTableLayout')
        self.positionDetailTableLayout.addWidget(self.positionDetailTable)
        # self.positionDetailTable.set_account_event_type(self.event_type['position_detail'])

        # 平仓明细表格
        self.closedPositionTable = ClosedPositionMonitor(account_engine=self.account_server,
                                                         account_event=self.trade_event_engine, parent=self)
        self.closedPositionTableLayout = QtWidgets.QVBoxLayout(self.tabClosedPosition)
        self.closedPositionTableLayout.setObjectName('closedPositionTableLayout')
        self.closedPositionTableLayout.addWidget(self.closedPositionTable)

    def register_widget_events(self):
        """注册控件事件"""
        self.pbQryAccount.clicked.connect(self.pbQryAccountClicked)
        self.pbQryOrder.clicked.connect(self.pbQryOrderClicked)
        self.pbDeleteOrder.clicked.connect(self.pbDeleteOrderClicked)
        self.pbRefreshAccount.clicked.connect(self.pbRefreshAccount_clicked)
        self.pbRefreshOrder.clicked.connect(self.pbRefreshOrder_clicked)

    def pbQryAccountClicked(self):
        """query account"""
        # 账户查询
        evt = Event(event_type=EVENT_RQ_ACCOUNT)
        if self.trade_event_engine:
            self.trade_event_engine.put(evt)
        elif self.data_server:
            self.data_server.data_event_engine.put(evt)

        # 持仓查询
        time.sleep(1)
        evt = Event(event_type=EVENT_RQ_POSITION)
        if self.trade_event_engine:
            self.trade_event_engine.put(evt)
        elif self.data_server:
            self.data_server.data_event_engine.put(evt)
        # 持仓明细查询
        time.sleep(1)
        evt = Event(event_type=EVENT_RQ_POSITION_DETAIL)
        if self.trade_event_engine:
            self.trade_event_engine.put(evt)
        # 成交查询
        time.sleep(1)
        evt = Event(event_type=EVENT_RQ_TRADE)
        if self.trade_event_engine:
            self.trade_event_engine.put(evt)
        # 委托查询
        time.sleep(1)
        evt = Event(event_type=EVENT_RQ_ORDER)
        if self.trade_event_engine:
            self.trade_event_engine.put(evt)
        # elif self.data_server:
        #     self.data_server.data_event_engine.put(evt)

    def pbQryOrderClicked(self):
        """query order 委托查询"""
        evt = Event(event_type=EVENT_RQ_ORDER)
        if self.trade_event_engine:
            self.trade_event_engine.put(evt)
        elif self.data_server:
            self.data_server.data_event_engine.put(evt)

    def pbDeleteOrderClicked(self):
        """ delete untraded order"""

    def pbRefreshOrder_clicked(self):
        """"""

    def pbRefreshAccount_clicked(self):
        """"""
        self.pbQryAccountClicked()


class TechAnalysis(TABase, Ui_FormTA):
    """技术分析界面"""

    def __init__(self, parent=None, quote_event=None):
        super(TechAnalysis, self).__init__()
        self.setupUi(self)
        self.iniUI()

    def iniUI(self):
        # self.dwQuoteDetail.setWindowFlags(Qt.FramelessWindowHint)
        self.dwQuoteTotal.setWindowFlags(Qt.FramelessWindowHint)
        self.tick_widget = TickWidget()
        self.bar_widget = KLineWidget()
        self.loTa.addWidget(self.bar_widget)
        self.twTickDetail.setSpan(0, 0, 1, 2)  # 合并第一行的1-2两列
        self.twTickDetail.setSpan(0, 2, 1, 2)  # 合并第一行的3-4两列
        self.instrument_info_btn = QtWidgets.QTableWidgetItem('资讯')
        self.twTickDetail.setItem(0, 2, self.instrument_info_btn)


def main():
    import sys
    from PyQt6.QtWidgets import QApplication
    # from app.work_frame import BQ
    from ctp.py_ctp.main import BQ

    wf = BQ()

    app = QApplication(sys.argv)
    # window = UITT(data_server=wf.data_server, quote_event=wf.quote_event_engine, trade_event=wf.trade_event_engine,
    #               db_client=wf.db_client)
    window = UITT(data_server=wf.qe, quote_event=wf.qe, trade_event=wf.te,
                  db_client=wf._db_all)
    # StrategyBacktest()  # StrategyRunningMonitor()  # DataManager()  # TechAnalysis  UITT  BankInvestor

    window.show()

    sys.exit(app.exec())


if __name__ == '__main__':
    main()
